<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>分子结构可视化 (X3DOM实现)</title>
    <script type="text/javascript" src="https://www.x3dom.org/download/x3dom.js"></script>
    <link rel="stylesheet" href="https://www.x3dom.org/download/x3dom.css">
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: white;
            min-height: 100vh;
        }
        .container {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        .header {
            text-align: center;
            padding: 15px;
            background: rgba(0, 0, 0, 0.3);
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
        }
        .header h1 {
            margin: 0;
            font-size: 2.2em;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }
        .header p {
            margin: 10px 0 0;
            font-size: 1.1em;
            max-width: 800px;
            margin-left: auto;
            margin-right: auto;
        }
        .content {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
        }
        .controls {
            flex: 1;
            min-width: 300px;
            background: rgba(0, 0, 0, 0.3);
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
        }
        .visualization {
            flex: 2;
            min-width: 500px;
            height: 500px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 10px 10px 0 0;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            overflow: hidden;
        }
        .visualization-footer {
            background: rgba(0, 0, 0, 0.3);
            border-radius: 0 0 10px 10px;
            padding: 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            margin-bottom: 20px;
        }
        .molecule-info {
            flex: 1;
            padding: 10px;
        }
        .molecule-info h4 {
            margin-top: 0;
            margin-bottom: 10px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.2);
            padding-bottom: 5px;
        }
        .molecule-info p {
            margin: 5px 0;
            font-size: 0.95em;
        }
        .legend {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
            padding: 10px;
            justify-content: center;
        }
        .legend-item {
            display: flex;
            align-items: center;
            gap: 5px;
        }
        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 50%;
        }
        .center-atom { background-color: #8B4513; }
        .bonded-atom { background-color: #FF4136; }
        .lone-pair { background-color: #0074D9; }
        .bond { background-color: #AAAAAA; }
        .control-group {
            margin-bottom: 20px;
        }
        .control-group h3 {
            margin-top: 0;
            border-bottom: 2px solid rgba(255, 255, 255, 0.3);
            padding-bottom: 8px;
        }
        .slider-container {
            margin: 15px 0;
        }
        .slider-container label {
            display: block;
            margin-bottom: 5px;
            font-weight: 500;
        }
        .slider {
            width: 100%;
            height: 10px;
            border-radius: 5px;
            background: rgba(255, 255, 255, 0.1);
            outline: none;
        }
        .value-display {
            display: inline-block;
            width: 30px;
            text-align: center;
            font-weight: bold;
        }
        .examples {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 10px;
            margin-top: 15px;
        }
        .example-btn {
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 255, 255, 0.3);
            color: white;
            padding: 10px;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s ease;
            text-align: center;
        }
        .example-btn:hover {
            background: rgba(255, 255, 255, 0.2);
            transform: translateY(-2px);
        }
        #x3d-canvas {
            width: 100%;
            height: 100%;
            border-radius: 8px;
        }
        .instructions {
            background: rgba(0, 0, 0, 0.3);
            padding: 15px;
            border-radius: 10px;
            margin-top: 20px;
        }
        .instructions h3 {
            margin-top: 0;
        }
        
        .ai-footer {
            font-size: 0.9em;
            text-align: center;
        }
        
        .footer-content {
            max-width: 800px;
            margin: 0 auto;
            padding: 0 20px;
        }
        
        .ai-footer p {
            margin: 5px 0;
            color: rgba(255, 255, 255, 0.7);
        }
        
        .ai-footer p:first-child {
            font-style: italic;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>分子结构可视化</h1>
            <p>调整参数查看不同基础分子构型，或从示例中选择常见分子结构。</p>
        </div>
        
        <div class="content">
            <div class="controls">
                <div class="control-group">
                    <h3>分子构型参数</h3>
                    <div class="slider-container">
                        <label>配体数 (N_PAIRS): <span id="pairs-value" class="value-display">4</span></label>
                        <input type="range" min="0" max="4" value="4" class="slider" id="pairs-slider">
                    </div>
                    <div class="slider-container">
                        <label>孤对电子数 (N_ELECTRONS): <span id="electrons-value" class="value-display">2</span></label>
                        <input type="range" min="0" max="4" value="2" class="slider" id="electrons-slider">
                    </div>
                </div>
                
                <div class="control-group">
                    <h3>示例分子</h3>
                    <div class="examples">
                        <div class="example-btn" data-pairs="2" data-electrons="0">CO₂ (直线形)</div>
                        <div class="example-btn" data-pairs="3" data-electrons="0">BF₃ (三角形)</div>
                        <div class="example-btn" data-pairs="4" data-electrons="0">CH₄ (四面体)</div>
                        <div class="example-btn" data-pairs="4" data-electrons="1">NH₃ (三角锥)</div>
                        <div class="example-btn" data-pairs="4" data-electrons="2">H₂O (角形)</div>
                        <div class="example-btn" data-pairs="0" data-electrons="0">单原子</div>
                    </div>
                </div>
            </div>
            
            <div class="visualization-container">
                <div class="visualization">
                    <x3d width="100%" height="100%">
                        <scene>
                            <viewpoint position="0 0 10"></viewpoint>
                            <transform id="molecule-transform">
                                <!-- Molecule will be generated here -->
                            </transform>
                        </scene>
                    </x3d>
                </div>
                
                <div class="visualization-footer">
                    <div class="molecule-info">
                        <h4>当前分子结构信息</h4>
                        <p id="molecule-name">水分子 (H₂O)</p>
                        <p id="molecule-shape">角形</p>
                        <p id="molecule-desc">中心原子连接2个原子，有2对孤对电子</p>
                    </div>
                    
                    <div class="legend">
                        <div class="legend-item">
                            <div class="legend-color center-atom"></div>
                            <span>中心原子</span>
                        </div>
                        <div class="legend-item">
                            <div class="legend-color bonded-atom"></div>
                            <span>配体原子</span>
                        </div>
                        <div class="legend-item">
                            <div class="legend-color lone-pair"></div>
                            <span>孤对电子</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="instructions">
            <h3>操作指南</h3>
            <p>• 使用鼠标左键旋转分子模型</p>
            <p>• 调整滑块改变分子构型参数</p>
            <p>• 点击示例分子按钮查看常见分子结构</p>
            <p>• 分子结构信息和图例位于3D模型下方</p>
        </div>
    </div>
    
    <footer class="ai-footer">
        <div class="footer-content">
            <p>AI生成内容，仅供演示，不构成专业化学建议。</p>
        </div>
    </footer>

    <script>
        // 原子半径
        const r0 = 0.55; // 中心原子半径
        const r1 = 0.45; // 配体原子半径
        
        // 当前分子参数
        let nPairs = 4;
        let nElectrons = 2;
        
        // 分子信息映射
        const moleculeInfo = {
            '0_0': { name: '单原子', shape: '单原子', desc: '仅有一个中心原子' },
            '1_0': { name: '双原子分子', shape: '直线形', desc: '中心原子连接1个原子' },
            '2_0': { name: '二氧化碳 (CO₂)', shape: '直线形', desc: '中心原子连接2个原子' },
            '3_0': { name: '三氟化硼 (BF₃)', shape: '三角形', desc: '中心原子连接3个原子' },
            '4_0': { name: '甲烷 (CH₄)', shape: '四面体', desc: '中心原子连接4个原子' },
            '4_1': { name: '氨 (NH₃)', shape: '三角锥', desc: '中心原子连接3个原子，有1对孤对电子' },
            '4_2': { name: '水 (H₂O)', shape: '角形', desc: '中心原子连接2个原子，有2对孤对电子' }
        };
        
        // 获取元素
        const pairsSlider = document.getElementById('pairs-slider');
        const electronsSlider = document.getElementById('electrons-slider');
        const pairsValue = document.getElementById('pairs-value');
        const electronsValue = document.getElementById('electrons-value');
        const moleculeName = document.getElementById('molecule-name');
        const moleculeShape = document.getElementById('molecule-shape');
        const moleculeDesc = document.getElementById('molecule-desc');
        const moleculeTransform = document.getElementById('molecule-transform');
        const exampleBtns = document.querySelectorAll('.example-btn');
        
        // 更新分子信息显示
        function updateMoleculeInfo() {
            const key = `${nPairs}_${nElectrons}`;
            const info = moleculeInfo[key] || { 
                name: '自定义分子', 
                shape: '自定义形状',
                desc: `中心原子连接${Math.max(0, nPairs - nElectrons)}个原子，有${nElectrons}对孤对电子`
            };
            
            moleculeName.textContent = info.name;
            moleculeShape.textContent = info.shape;
            moleculeDesc.textContent = info.desc;
        }
        
        // 计算原子位置
        function calculateAtomPositions() {
            const atoms = [{x: 0, y: 0, z: 0, type: 'center'}]; // 中心原子
            
            switch(nPairs) {
                case 0:
                    // 只有中心原子
                    break;
                case 1:
                    // 直线形
                    atoms.push({x: r0 + r1, y: 0, z: 0, type: 'bonded'});
                    break;
                case 2:
                    // 直线形
                    atoms.push({x: r0 + r1, y: 0, z: 0, type: 'bonded'});
                    atoms.push({x: -(r0 + r1), y: 0, z: 0, type: 'bonded'});
                    break;
                case 3:
                    // 三角形
                    const a3 = Math.sqrt(3) * (r0 + r1);
                    atoms.push({x: a3/2, y: Math.sqrt(3)/6 * a3, z: 0, type: 'bonded'});
                    atoms.push({x: 0, y: 0, z: 0, type: 'bonded'});
                    atoms.push({x: a3, y: 0, z: 0, type: 'bonded'});
                    atoms.push({x: a3/2, y: Math.sqrt(3)/2 * a3, z: 0, type: 'bonded'});
                    
                    // 调整位置使中心原子在原点
                    const center3 = {x: a3/2, y: Math.sqrt(3)/6 * a3, z: 0};
                    for (let i = 1; i < atoms.length; i++) {
                        atoms[i].x -= center3.x;
                        atoms[i].y -= center3.y;
                        atoms[i].z -= center3.z;
                    }
                    atoms[0].x = 0;
                    atoms[0].y = 0;
                    atoms[0].z = 0;
                    break;
                case 4:
                    // 四面体
                    const a4 = Math.sqrt(8/3) * (r0 + r1);
                    atoms.push({x: a4/2, y: Math.sqrt(3)/6 * a4, z: Math.sqrt(6)/12 * a4, type: 'bonded'});
                    atoms.push({x: 0, y: 0, z: 0, type: 'bonded'});
                    atoms.push({x: a4, y: 0, z: 0, type: 'bonded'});
                    atoms.push({x: a4/2, y: Math.sqrt(3)/2 * a4, z: 0, type: 'bonded'});
                    atoms.push({x: a4/2, y: Math.sqrt(3)/6 * a4, z: Math.sqrt(6)/3 * a4, type: 'bonded'});
                    
                    // 调整位置使中心原子在原点
                    const center4 = {x: a4/2, y: Math.sqrt(3)/6 * a4, z: Math.sqrt(6)/12 * a4};
                    for (let i = 1; i < atoms.length; i++) {
                        atoms[i].x -= center4.x;
                        atoms[i].y -= center4.y;
                        atoms[i].z -= center4.z;
                    }
                    atoms[0].x = 0;
                    atoms[0].y = 0;
                    atoms[0].z = 0;
                    break;
            }
            
            // 标记孤对电子
            if (nElectrons > 0) {
                // 从最后一个原子开始标记为孤对电子
                const startIndex = Math.max(1, atoms.length - nElectrons);
                for (let i = startIndex; i < atoms.length; i++) {
                    atoms[i].type = 'lonePair';
                }
            }
            
            return atoms;
        }
        
        // 生成分子结构的X3DOM节点
        function generateMolecule() {
            const atoms = calculateAtomPositions();
            let html = '';
            
            // 创建原子球体
            atoms.forEach(atom => {
                let color, transparency;
                
                switch(atom.type) {
                    case 'center':
                        color = '0.545 0.271 0.075'; // 棕色
                        transparency = 0;
                        break;
                    case 'bonded':
                        color = '1 0 0'; // 红色
                        transparency = 0;
                        break;
                    case 'lonePair':
                        color = '0 0.5 1'; // 蓝色
                        transparency = 0.3;
                        break;
                }
                
                html += `
                    <transform translation="${atom.x} ${atom.y} ${atom.z}">
                        <shape>
                            <appearance>
                                <material diffuseColor="${color}" transparency="${transparency}"></material>
                            </appearance>
                            <sphere radius="${atom.type === 'center' ? r0 : r1}"></sphere>
                        </shape>
                    </transform>
                `;
            });
           
            return html;
        }
        
        // 创建两个原子之间的键
        function createBond(atom1, atom2) {
            const dx = atom2.x - atom1.x;
            const dy = atom2.y - atom1.y;
            const dz = atom2.z - atom1.z;
            
            const distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
            const cx = (atom1.x + atom2.x) / 2;
            const cy = (atom1.y + atom2.y) / 2;
            const cz = (atom1.z + atom2.z) / 2;
            
            // 计算旋转角度
            const angle = Math.acos(dz / distance);
            const axis = dz === distance ? '1 0 0' : `${-dy} ${dx} 0`;
            
            return `
                <transform translation="${cx} ${cy} ${cz}" rotation="${axis} ${angle}">
                    <shape>
                        <appearance>
                            <material diffuseColor="0.7 0.7 0.7"></material>
                        </appearance>
                        <cylinder radius="0.05" height="${distance}"></cylinder>
                    </shape>
                </transform>
            `;
        }
        
        // 渲染分子
        function renderMolecule() {
            moleculeTransform.innerHTML = generateMolecule();
            updateMoleculeInfo();
            
            // 重新加载X3DOM场景
            if (typeof x3dom !== 'undefined') {
                x3dom.reload();
            }
        }
        
        // 事件监听器
        pairsSlider.addEventListener('input', function() {
            nPairs = parseInt(this.value);
            pairsValue.textContent = nPairs;
            
            // 确保电子数不超过配体数
            if (nElectrons > nPairs) {
                nElectrons = nPairs;
                electronsSlider.value = nElectrons;
                electronsValue.textContent = nElectrons;
            }
            electronsSlider.max = nPairs;
            
            renderMolecule();
        });
        
        electronsSlider.addEventListener('input', function() {
            nElectrons = parseInt(this.value);
            electronsValue.textContent = nElectrons;
            renderMolecule();
        });
        
        exampleBtns.forEach(btn => {
            btn.addEventListener('click', function() {
                nPairs = parseInt(this.dataset.pairs);
                nElectrons = parseInt(this.dataset.electrons);
                
                pairsSlider.value = nPairs;
                electronsSlider.value = nElectrons;
                pairsValue.textContent = nPairs;
                electronsValue.textContent = nElectrons;
                electronsSlider.max = nPairs;
                
                renderMolecule();
            });
        });
        
        // 初始渲染
        renderMolecule();
    </script>
</body>
</html>
